<template>
  <!--标题-->
  <custom-title-bar title="订单确认" background-color="#fff" />
  <!-- 内容 -->
  <view class="content-rol" :style="{ top: view.topBar.bottom + 'px' }">
    <!--收货方式-联动内容-->
    <meal-fetch-fetch-method
      v-model:receiving-method="receivingMethodRef"
      :supportedReceivingMethods="confirmPageRequireInfo?.supportedReceivingMethods"
    />
    <view>
      <delivery-piece
        :shopId="shopId"
        :shopPredetermineInfo="shopPredetermineInfo"
        :selectedAddress="selectedAddress"
        ref="deliveryPieceRef"
        v-if="ReceivingMethod.DELIVERY === receivingMethodRef"
      />
      <shop-eat-piece :shopId="shopId" ref="shopEatPieceRef" v-if="ReceivingMethod.SHOP_EAT === receivingMethodRef" />
      <self-pickup-piece
        :shopPredetermineInfo="shopPredetermineInfo"
        ref="selfPickupPieceRef"
        v-if="ReceivingMethod.SELF_PICKUP === receivingMethodRef"
      />
    </view>
    <!-- 价格总览表 -->
    <price-summary-table
      :shopId="shopId"
      :shoppingCart="shoppingCart"
      :preferential-info="confirmPageRequireInfo?.preferentialInfo"
      :dishListSumPrice="confirmPageRequireInfo?.dishListSumPrice"
      :delivery-fee="confirmPageRequireInfo?.deliveryFee"
      :packingFee="confirmPageRequireInfo?.packingFee"
      :selectedShopCouponIds="selectedShopCouponIds"
      :selectedPlatformCouponIds="selectedPlatformCouponIds"
    />
    <!-- 用户备注 -->
    <!-- TODO 可以考虑自动获取同一家店铺上次购买的备注信息 -->
    <remark ref="remarkRef" />
  </view>
  <!-- 支付金额统计 -->
  <payment-amount-summary
    :height="paymentAmountSummaryContentHeight + 'px'"
    :preferential-info="confirmPageRequireInfo?.preferentialInfo"
    @submitOrder="submitOrder"
  />
  <simulate-payment ref="simulatePaymentRef" @cancel-payment="cancelPayment" @on-payment="paymentOrder" />
  <unpaid-popup ref="unpaidPopupRef" @to-pay="toPay" />
</template>

<script setup lang="ts">
import { onMounted, provide, ref, type Ref, watch } from 'vue'
import $store from '@/store'
import MealFetchFetchMethod from './meal-fetch-method/index.vue'
import CustomTitleBar from '@/components/custom-title-bar/index.vue'
import DeliveryPiece from './receiving-method-piece/delivery-piece/index.vue'
import SelfPickupPiece from './receiving-method-piece/self-pickup-piece/index.vue'
import ShopEatPiece from './receiving-method-piece/shop-eat-piece/index.vue'
import PriceSummaryTable from './price-summary-table/index.vue'
import Remark from './remark/index.vue'
import type { GeneratePredetermineDatesAndTimeRangesNeedInfo } from '@/components/predetermine-datetime-selector/utils.type'
import $API from '@/api'
import PaymentAmountSummary from './payment-amount-summary/index.vue'
import type { CartItemVO } from '@/types/response/shopping-cart'
import { RequestPayDTO, SubmitOrder } from '@/types/param/order'
import { $modal } from '@/plugins'
import SimulatePayment from '@/components/simulate-payment/index.vue'
import UnpaidPopup from './unpaid-popup/index.vue'
import type { CreateOrderComplete } from '@/types/response/order'
import useWXSubMessage from '@/hooks/useWXSubMessage'
import type { PaymentParams } from '@/components/simulate-payment/simulate-payment-type'
import { OrderConfirmRequire } from '@/types/response/shop'
import type { AddressBookResponse } from '@/types/response/address-book'
import { getCodeForLogin, requestUserPayment } from '@/helper/payHelper'
import { ReceivingMethod } from '@/enum/ReceivingMethod'
import { PayPlatformEnum } from '@/enum/PayPlatformEnum'

const { subscriber, mealPickupSubscribe, orderRefundSubscription } = useWXSubMessage()
const { view } = $store.app.getSystemParam()
const { seatNumber } = $store.shop

const query = defineProps<{
  shopId: string
  receivingMethod: string
  // longitude: number
  // latitude: number
}>()
const shopId = parseInt(query.shopId)
const receivingMethodRef = $store.shop.receivingMethod.getRef()
if (receivingMethodRef.value == null) {
  $store.shop.receivingMethod.setValue(query.receivingMethod)
}
// 预计时间相关
const shopPredetermineInfo = ref<GeneratePredetermineDatesAndTimeRangesNeedInfo>()

// 购物车信息
const shoppingCart = ref<CartItemVO[]>()
// 当receivingMethod改变时，需要重新请求数据
const selectedAddress = ref<AddressBookResponse>()
// 确认页后端返回的数据
const confirmPageRequireInfo = ref<OrderConfirmRequire>()
const selectedPlatformCouponIds = ref<number[]>([])
const selectedShopCouponIds = ref<number[]>([])
const isPlatformCouponFirst = ref(true)
async function refreshConfirmPageRequireInfo() {
  // 请求确认页需要的数据
  const confirmPageRequireInfoResult = await $API.shoppingCart.queryOrderConfirmRequire({
    shopId,
    seatNumber: seatNumber.getValue(),
    receivingMethod: receivingMethodRef.value!,
    addressBookId: selectedAddress.value?.id,
    isPlatformCouponFirst: isPlatformCouponFirst.value,
    platformCouponIds: selectedPlatformCouponIds.value,
    shopCouponIds: selectedShopCouponIds.value
  })
  if (confirmPageRequireInfoResult.success) {
    confirmPageRequireInfo.value = confirmPageRequireInfoResult.data
    if (confirmPageRequireInfoResult.data.addressBook != null) {
      selectedAddress.value = confirmPageRequireInfoResult.data.addressBook
    }
    shoppingCart.value = confirmPageRequireInfoResult.data.cartItemList
  }
}
// 当收到选择完平台优惠券时
$store.coupon.selectedPlatformCoupon.on((data) => {
  // 维护isPlatformCouponFirst
  isPlatformCouponFirst.value = selectedShopCouponIds.value == null || selectedShopCouponIds.value.length == 0
  // 取选择结果，并刷新相关请求
  selectedPlatformCouponIds.value = data == null ? [] : data
  refreshConfirmPageRequireInfo()
})
// 当收到选择完平台优惠券时
$store.coupon.selectedShopCoupon.on((data) => {
  // 取选择结果，并刷新相关请求
  selectedShopCouponIds.value = data == null ? [] : data
  refreshConfirmPageRequireInfo()
})
onMounted(async () => {
  // 向后端请求shopPredetermineInfo
  const shopPredetermineInfoResult = await $API.shop.shopPredetermineInfo(shopId)
  if (shopPredetermineInfoResult.success) shopPredetermineInfo.value = shopPredetermineInfoResult.data
})
// 当切换收货方式时
watch(
  () => [receivingMethodRef.value],
  () => refreshConfirmPageRequireInfo(),
  { immediate: true }
)

// 当地址改变时
$store.user.userChooseAddressEvent.on((newAddress) => {
  selectedAddress.value = newAddress
  refreshConfirmPageRequireInfo()
})
// 向下共享以下
provide<number>('shopId', shopId)
provide<Ref<GeneratePredetermineDatesAndTimeRangesNeedInfo | undefined>>('shopPredetermineInfo', shopPredetermineInfo)
// 提交订单信息收集
const shopEatPieceRef = ref()
const deliveryPieceRef = ref()
const selfPickupPieceRef = ref()
const remarkRef = ref()

const simulatePaymentRef = ref()
async function submitOrder() {
  // 收集上面与receivingMethod相关的
  const submitOrderParam = new SubmitOrder()
  if (ReceivingMethod.SHOP_EAT === receivingMethodRef.value) {
    submitOrderParam.seatNumber = shopEatPieceRef.value.seatNumber
    // 店食单，都是立即单，不需要指定
    submitOrderParam.isImmediate = null
    if (submitOrderParam.seatNumber == null) {
      $modal.toastErrorMsg('请扫一扫桌子上的座位码绑定座位号')
      return
    }
  } else if (ReceivingMethod.SELF_PICKUP === receivingMethodRef.value) {
    submitOrderParam.isImmediate = selfPickupPieceRef.value.isImmediate
    submitOrderParam.specifiedTime = selfPickupPieceRef.value.specifiedTime
    if (!submitOrderParam.isImmediate && submitOrderParam.specifiedTime == null) {
      $modal.toastErrorMsg('未成功指定时间，请选择时间')
    }
  } else if (ReceivingMethod.DELIVERY === receivingMethodRef.value) {
    submitOrderParam.addressBookId = deliveryPieceRef.value.addressBookId
    submitOrderParam.isImmediate = deliveryPieceRef.value.isImmediate
    submitOrderParam.specifiedTime = deliveryPieceRef.value.specifiedTime

    if (!submitOrderParam.isImmediate && submitOrderParam.specifiedTime == null) {
      $modal.toastErrorMsg('未成功指定时间，请选择时间')
    }
    if (submitOrderParam.addressBookId == null) {
      $modal.toastErrorMsg('需要选择地址')
    }
  }
  // 店铺id
  submitOrderParam.shopId = shopId
  // 交付方式
  submitOrderParam.receivingMethod = receivingMethodRef.value!
  // 备注信息
  submitOrderParam.remark = remarkRef.value.remarkText

  submitOrderParam.isPlatformCouponFirst = isPlatformCouponFirst.value
  submitOrderParam.shopCouponIds = selectedShopCouponIds.value
  submitOrderParam.platformCouponIds = selectedPlatformCouponIds.value
  //显示加载框
  const result = await $modal.showLoading('去支付', async () => {
    return await $API.order.create(submitOrderParam)
  })
  if (result == null || !result.success) {
    $modal.toastErrorMsg(`创建订单失败！${result?.message || ''}`)
    return
  }
  // 向用户发起订阅消息提醒权限
  subscriber(mealPickupSubscribe, orderRefundSubscription)

  // 弹出支付窗口
  simulatePaymentRef.value.callOut(result.data)
  unpaidPopupRef.value.setOrderInfo(result.data)
}
// 去支付
function toPay(createOrderComplete: CreateOrderComplete) {
  simulatePaymentRef.value.callOut(createOrderComplete)
  // 关闭待支付
  unpaidPopupRef.value.close()
}
// 当用户取消支付时
const unpaidPopupRef = ref()
function cancelPayment() {
  // 弹出订单信息，尝试让用户再支付，用户取消可能是订单信息不确定
  unpaidPopupRef.value.callOut()
}
// 支付
const payInfo = ref<{ [key: string]: String }>()

async function paymentOrder(createOrderComplete: PaymentParams, isPaying: Ref<boolean>) {
  try {
    if (payInfo.value == null) {
      const code = await getCodeForLogin()
      const requestPayDTO = new RequestPayDTO(PayPlatformEnum.WECHAT_PAY, 'jsapi', createOrderComplete.orderId, code)
      const resultForSystem = await $API.order.requestPay(requestPayDTO)
      console.log('请求后台支付，返回数据：', resultForSystem)
      if (!resultForSystem.success) {
        $modal.toastErrorMsg('请求支付失败！' + resultForSystem.message)
      }
      payInfo.value = resultForSystem.data
    } else {
      console.log('有值重新调起支付')
    }
    const resultForUser = await requestUserPayment(payInfo.value)
    // console.log('请求用户支付，结果：', resultForUser)
    if (resultForUser.success) {
      // 如果是自提，需要获取可以向用户提示的发订阅消息允许
      uni.navigateTo({ url: `/pages/order-pages/order-detail/index?orderId=${createOrderComplete.orderId}` })
      simulatePaymentRef.value.hide()
      $store.order.placeOrderEvent.emit()
    }
  } finally {
    isPaying.value = false
  }
}

// style vars
const paymentAmountSummaryContentHeight = 60
const paymentAmountSummaryBottomSafeHeight = $store.app.getSystemParam().safeArea?.bottom
const paymentAmountSummaryHeight =
  paymentAmountSummaryContentHeight + (paymentAmountSummaryBottomSafeHeight ?? 0) + 'px'
</script>

<style scoped lang="scss">
.content-rol {
  position: fixed;
  bottom: v-bind(paymentAmountSummaryHeight);

  /* content-rol需要在payment-amount-summary、custom-title-bar上层，不然content-rol里面的弹窗就不是最上面的 */
  z-index: 100;
  overflow: auto;
  padding: 30rpx;
  width: 100vw;
  background-color: #f5f5f5;
  box-sizing: border-box;
}
</style>
